#include <cstdio>
#include <clang-c/Index.h>
#include "llvm/Support/CommandLine.h"

using namespace llvm;

void print_node(CXCursor cursor, int indent) {
	CXString cursorSpelling = clang_getCursorSpelling(cursor);
	CXString cursorKindName = clang_getCursorKindSpelling(clang_getCursorKind(cursor));

	for (int i = 0; i < indent; i++) {
		printf("  ");
	}

	printf("%s (%s)\n", clang_getCString(cursorSpelling), clang_getCString(cursorKindName));

	clang_disposeString(cursorSpelling);
	clang_disposeString(cursorKindName);

	clang_visitChildren(cursor, [](CXCursor c, CXCursor parent, CXClientData client_data) -> CXChildVisitResult {
			print_node(c, *(int *)client_data + 1);
			return CXChildVisit_Continue;
			}, &indent);
}

int main(int argc, char** argv) {
	// commandline options
	static cl::opt<std::string> file_name(cl::Positional, cl::desc("input file"), cl::Required);
	cl::ParseCommandLineOptions(argc, argv, "dump ast demo\n");

	// create clang index
	CXIndex index = clang_createIndex(0, 0);

	// compiler commandline
	const char *command_line_args[] = {
		"-std=c++11",
	};

	int arg_num = 1;

	// parser options
	unsigned options = CXTranslationUnit_None;

	// parse source code
	CXTranslationUnit trans_unit = clang_parseTranslationUnit(
			index, file_name.c_str(), command_line_args, arg_num, NULL, 0, options);

	if (!trans_unit) {
		fprintf(stderr, "Failed to parse the source file\n");
		return 1;
	}

	// get the root of AST tree
	CXCursor rootCursor = clang_getTranslationUnitCursor(trans_unit);

	// prnt AST tree
	int initialIndent = 0;
	print_node(rootCursor, initialIndent);

	// release the resource
	clang_disposeTranslationUnit(trans_unit);
	clang_disposeIndex(index);

	return 0;
}
